using System;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using RestSharp;

namespace Comteck.Ktt.Services.Plugs.EMS {
  public class EMSClient {
    private readonly RestClient _restClient;

    private const string BASE_URL = "https://api.ems.com.cn/jdpt-amp-back-web";

    public EMSClientOptions ClientOptions { get; set; }

    public EMSClient(EMSClientOptions clientOptions) {
      ClientOptions = clientOptions;
      _restClient = new RestClient(new RestClientOptions {
        BaseUrl = ((ClientOptions.BaseUrl == null) ? new Uri("https://api.ems.com.cn/jdpt-amp-back-web") : ClientOptions.BaseUrl),
        RemoteCertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => true
      });
    }

    public async Task<BaseResponse<TOut>> ExecuteAsync<TIn, TOut>(Guid serialNo, TIn logisticsInterface) {
      if (ClientOptions.Authorization == null) {
        throw new Exception("Authorization is not null");
      }

      if (ClientOptions.SenderNo == null) {
        throw new Exception("SenderNo is not null");
      }

      if (ClientOptions.Key == null) {
        throw new Exception("Key is not null");
      }

      RestRequest request = new RestRequest();
      if (!ClientOptions.ApiCode.HasValue) {
        string value = Regex.Match(logisticsInterface.GetType().FullName, "M(?<ModuleName>0\\d{5})").Groups["ModuleName"].Value;
        request.AddQueryParameter("apiCode", value.Replace("M", ""));
      } else {
        request.AddQueryParameter("apiCode", ClientOptions.ApiCode.ToString().Split('_')[1]);
      }

      request.AddQueryParameter("senderNo", ClientOptions.SenderNo);
      request.AddQueryParameter("serialNo", serialNo.ToString());
      request.AddQueryParameter("msgType", ClientOptions.MsgType);
      request.AddQueryParameter("authorization", ClientOptions.Authorization);
      request.AddQueryParameter("version", ClientOptions.Version ?? "V1.0.0");
      request.AddQueryParameter("timeStamp", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
      var settings = new JsonSerializerSettings {
        ContractResolver = new CamelCasePropertyNamesContractResolver()
      };
      string text = JsonConvert.SerializeObject(logisticsInterface, settings);
      text = SM4Crypto.Sm4Encrypt(text + ClientOptions.Key, SM4Crypto.Base64TryDecode(ClientOptions.Key));
      request.AddQueryParameter("logitcsInterface", "|$4|" + text);
      var restResponse = await _restClient.ExecutePostAsync<BaseResponse<TOut>>(request);
      if (restResponse.Data != null && restResponse.Data.Success) {
        restResponse.Data.RetBodyObject = JsonConvert.DeserializeObject<TOut>(restResponse.Data.RetBody.Replace("\\", ""));
      }

      return restResponse.Data;
    }

    public EMSClientOptions GetCurrentOptions() {
      return ClientOptions;
    }


  }
}
